﻿using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using Easy.Common.RegisterType;
using Easy.Common;
using Microsoft.Practices.ServiceLocation;
using System.Linq;

namespace Easy.ServiceLocator.Unity
{
    public static class EasyUnity
    {
        private static IServiceLocator _unityServiceLocator;
        private static UnityContainer unityContainer;
        private static object _lock = new object();

        static EasyUnity()
        {
            _unityServiceLocator = GetSingletonContainer();
        }


        #region public 初始化 IOC 容器

        public static IServiceLocator GetSingletonContainer()
        {
            if (_unityServiceLocator == null)
            {
                lock (_lock)
                {
                    if (_unityServiceLocator == null)
                    {
                        unityContainer = new UnityContainer();

                        //添加默认拦截器
                        unityContainer.AddNewExtension<Interception>();

                        Microsoft.Practices.ServiceLocation.ServiceLocator
                            .SetLocatorProvider(() => new UnityServiceLocator(unityContainer));

                        _unityServiceLocator = new UnityServiceLocator(unityContainer);
                    }
                }
            }

            return _unityServiceLocator;
        }


        public static UnityContainer UnityContainer
        {
            get
            {
                return unityContainer;
            }
        }

        #endregion


        #region public 自动完成类型注册

        /// <summary>
        /// 根据传入的类型信息，自动向容器中注册类型
        /// </summary>
        /// <param name="regInfolst">需要注册的类型</param>
        public static void AutoRegisterType(IList<RegisterTypeInfo> regInfolst)
        {
            CheckHelper.ArrayNotHasNull(regInfolst, "regInfolst");

            //检查所有配置是否正确
            RegisterTypeChecker registerTypeChecker = new RegisterTypeChecker();

            registerTypeChecker.Check(regInfolst);


            foreach (var regInfo in regInfolst)
            {
                if (Type.Equals(regInfo.BaseType, regInfo.ImplementationType))
                {
                    RegisterMe(regInfo);
                }
                else
                {
                    RegisterParent(regInfo);
                }
            }
        }


        private static void RegisterMe(RegisterTypeInfo regInfo)
        {
            //获取生命周期
            LifetimeManager lifetimeManager = GetLifetimeManager(regInfo.IocLifetime);

            if (regInfo.InterceptorType == InterceptorType.None)
            {
                unityContainer.RegisterType(regInfo.BaseType, lifetimeManager);
            }
            else
            {
                InterceptionMember[] interceptionMember = GetInterceptionMember(regInfo.InterceptorType);

                unityContainer.RegisterType(regInfo.BaseType,
                 lifetimeManager,
                 interceptionMember);
            }
        }


        private static void RegisterParent(RegisterTypeInfo regInfo)
        {
            //获取生命周期
            LifetimeManager lifetimeManager = GetLifetimeManager(regInfo.IocLifetime);

            if (regInfo.InterceptorType == InterceptorType.None)
            {
                unityContainer.RegisterType(regInfo.BaseType,
                    regInfo.ImplementationType,
                    lifetimeManager);
            }
            else
            {
                InterceptionMember[] interceptionMember = GetInterceptionMember(regInfo.InterceptorType);

                unityContainer.RegisterType(regInfo.BaseType,
                    regInfo.ImplementationType,
                    lifetimeManager,
                    interceptionMember);
            }
        }

        #endregion


        #region private 获取生命周期、拦截器类型

        /// <summary>
        /// 获取 IOC 生命周期实例
        /// </summary>
        private static LifetimeManager GetLifetimeManager(IocLifeTime iocLifeTime)
        {
            LifetimeManager lifetimeManager;

            switch (iocLifeTime)
            {
                case IocLifeTime.New:
                    lifetimeManager = new TransientLifetimeManager();
                    break;
                case IocLifeTime.Singleton:
                    lifetimeManager = new ContainerControlledLifetimeManager();
                    break;
                case IocLifeTime.PerThread:
                    lifetimeManager = new PerThreadLifetimeManager();
                    break;
                case IocLifeTime.Externally:
                    lifetimeManager = new ExternallyControlledLifetimeManager();
                    break;
                default:
                    lifetimeManager = new TransientLifetimeManager();
                    break;
            }

            return lifetimeManager;
        }

        /// <summary>
        /// 获取 IOC 拦截器类型
        /// </summary>
        private static InterceptionMember[] GetInterceptionMember(InterceptorType interceptorType)
        {
            var interceptionMembers = new List<InterceptionMember>();

            interceptionMembers.Add(new InterceptionBehavior<PolicyInjectionBehavior>());


            switch (interceptorType)
            {
                case InterceptorType.TransparentProxy:
                    interceptionMembers.Add(new Interceptor<TransparentProxyInterceptor>());
                    break;
                case InterceptorType.Interface:
                    interceptionMembers.Add(new Interceptor<InterfaceInterceptor>());
                    break;
                case InterceptorType.VirtualMethod:
                    interceptionMembers.Add(new Interceptor<VirtualMethodInterceptor>());
                    break;
            }

            return interceptionMembers.ToArray();
        }

        #endregion
    }
}
